﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Net.Security;
using System.Security.Cryptography;
using System.Security.Cryptography.X509Certificates;
using System.Text;

namespace QQZiFramework
{


    public class CryptUtils
    {

        public static Dictionary<string, string> ParseKeyValueString(string keyValueString)
        {
            int noBreak = 0;
            Dictionary<string, string> result = new Dictionary<string, string>();
            StringReader sr = new StringReader(keyValueString);
            char[] buff = new char[1];
            int index = 0;
            StringBuilder sb = new StringBuilder();
            while (sr.Read(buff, index, 1) != 0)
            {
                if (buff[0] == '{')
                    noBreak++;
                if (buff[0] == '}')
                    noBreak--;

                if (buff[0] == '&' && noBreak == 0)
                {
                    string keyvalue = sb.ToString();
                    result.Add(keyvalue.Remove(keyvalue.IndexOf("=")), keyvalue.Substring(keyvalue.IndexOf("=") + 1));
                    sb = new StringBuilder();
                    continue;
                }
                sb.Append(buff);
            }
            if (sb.Length > 0)
            {
                string keyvalue = sb.ToString();
                result.Add(keyvalue.Remove(keyvalue.IndexOf("=")), keyvalue.Substring(keyvalue.IndexOf("=") + 1));
            }
            sr.Close();
            return result;
        }

        public static byte[] AESEncrypt(byte[] Data, string Key)
        {
            RijndaelManaged rm = new RijndaelManaged
            {
                Key = Convert.FromBase64String(Key),
                Mode = CipherMode.ECB,
                Padding = PaddingMode.PKCS7
            };

            ICryptoTransform cTransform = rm.CreateEncryptor();
            byte[] resultArray = cTransform.TransformFinalBlock(Data, 0, Data.Length);

            return resultArray;
        }

        public static byte[] AESDecrypt(byte[] Data, string Key)
        {

            RijndaelManaged rm = new RijndaelManaged
            {
                Key = Convert.FromBase64String(Key),
                Mode = CipherMode.ECB,
                Padding = PaddingMode.PKCS7
            };

            ICryptoTransform cTransform = rm.CreateDecryptor();
            byte[] resultArray = cTransform.TransformFinalBlock(Data, 0, Data.Length);

            return resultArray;
        }


        public static string GuidTo16String()
        {
            string dic = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
            int keylen = dic.Length;
            long x = 1;
            foreach (byte b in Guid.NewGuid().ToByteArray())
                x *= ((int)b + 1);
            string value = string.Empty;
            Random ra = new Random((int)(x & 0xffffffffL) | (int)(x >> 32));
            for (int i = 0; i < 16; i++)
            {
                value += dic[ra.Next() % keylen];
            }
            return value;
        }

        public static string getStringFromBytes(byte[] hexbytes, Encoding enc)
        {
            return enc.GetString(hexbytes);
        }

        public static byte[] getBytesFromString(string str, Encoding enc)
        {
            return enc.GetBytes(str);
        }

        public static byte[] asc2hex(string hexString)
        {

            byte[] returnBytes = new byte[hexString.Length / 2];
            for (int i = 0; i < returnBytes.Length; i++)
                returnBytes[i] = Convert.ToByte(hexString.Substring(i * 2, 2), 16);
            return returnBytes;
        }

        public static string hex2asc(byte[] hexbytes)
        {
            return BitConverter.ToString(hexbytes).Replace("-", string.Empty);

        }
        /// <summary>   
        /// RSA解密   要加密较长的数据，则可以采用分段加解密的方式
        /// </summary>   
        /// <param name="xmlPrivateKey"></param>   
        /// <param name="EncryptedBytes"></param>   
        /// <returns></returns>   
        public static byte[] RSADecrypt(string xmlPrivateKey, byte[] EncryptedBytes)
        {

            using (RSACryptoServiceProvider RSACryptography = new RSACryptoServiceProvider())
            {
                RSACryptography.FromXmlString(xmlPrivateKey);


                int MaxBlockSize = RSACryptography.KeySize / 8;    //解密块最大长度限制

                if (EncryptedBytes.Length <= MaxBlockSize)
                    return RSACryptography.Decrypt(EncryptedBytes, false);

                using (MemoryStream CrypStream = new MemoryStream(EncryptedBytes))
                using (MemoryStream PlaiStream = new MemoryStream())
                {
                    Byte[] Buffer = new Byte[MaxBlockSize];
                    int BlockSize = CrypStream.Read(Buffer, 0, MaxBlockSize);

                    while (BlockSize > 0)
                    {
                        Byte[] ToDecrypt = new Byte[BlockSize];
                        Array.Copy(Buffer, 0, ToDecrypt, 0, BlockSize);

                        Byte[] Plaintext = RSACryptography.Decrypt(ToDecrypt, false);
                        PlaiStream.Write(Plaintext, 0, Plaintext.Length);

                        BlockSize = CrypStream.Read(Buffer, 0, MaxBlockSize);
                    }

                    return PlaiStream.ToArray();
                }
            }
        }


        /// <summary>   
        /// RSA加密   要加密较长的数据，则可以采用分段加解密的方式
        /// </summary>   
        /// <param name="xmlPublicKey"></param>   
        /// <param name="SourceBytes"></param>   
        /// <returns></returns>   
        public static byte[] RSAEncrypt(string xmlPublicKey, byte[] SourceBytes)
        {
            using (RSACryptoServiceProvider RSACryptography = new RSACryptoServiceProvider())
            {
                RSACryptography.FromXmlString(xmlPublicKey);

                int MaxBlockSize = RSACryptography.KeySize / 8 - 11;    //加密块最大长度限制

                if (SourceBytes.Length <= MaxBlockSize)
                    return RSACryptography.Encrypt(SourceBytes, false);

                using (MemoryStream PlaiStream = new MemoryStream(SourceBytes))
                using (MemoryStream CrypStream = new MemoryStream())
                {
                    Byte[] Buffer = new Byte[MaxBlockSize];
                    int BlockSize = PlaiStream.Read(Buffer, 0, MaxBlockSize);

                    while (BlockSize > 0)
                    {
                        Byte[] ToEncrypt = new Byte[BlockSize];
                        Array.Copy(Buffer, 0, ToEncrypt, 0, BlockSize);

                        Byte[] Cryptograph = RSACryptography.Encrypt(ToEncrypt, false);
                        CrypStream.Write(Cryptograph, 0, Cryptograph.Length);

                        BlockSize = PlaiStream.Read(Buffer, 0, MaxBlockSize);
                    }

                    return CrypStream.ToArray();
                }
            }
        }

        /// <summary>
        /// 使用私钥签名
        /// </summary>
        /// <param name="SourceBytes">原始数据</param>
        /// <returns></returns>
        public static byte[] RSASign(string privateKey, byte[] SourceBytes)
        {
            using (RSACryptoServiceProvider _privateKeyRsaProvider = new RSACryptoServiceProvider())
            {
                _privateKeyRsaProvider.FromXmlString(privateKey);
                var signatureBytes = _privateKeyRsaProvider.SignData(SourceBytes, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1);
                return signatureBytes;
            }
        }

        public static RSA CreateRsaProviderFromPrivateKey(string privateKey)
        {
            var privateKeyBits = Convert.FromBase64String(privateKey);

            var rsa = RSA.Create();
            var rsaParameters = new RSAParameters();

            using (BinaryReader binr = new BinaryReader(new MemoryStream(privateKeyBits)))
            {
                byte bt = 0;
                ushort twobytes = 0;
                twobytes = binr.ReadUInt16();
                if (twobytes == 0x8130)
                    binr.ReadByte();
                else if (twobytes == 0x8230)
                    binr.ReadInt16();
                else
                    throw new Exception("Unexpected value read binr.ReadUInt16()");

                twobytes = binr.ReadUInt16();
                if (twobytes != 0x0102)
                    throw new Exception("Unexpected version");

                bt = binr.ReadByte();
                if (bt != 0x00)
                    throw new Exception("Unexpected value read binr.ReadByte()");

                rsaParameters.Modulus = binr.ReadBytes(GetIntegerSize(binr));
                rsaParameters.Exponent = binr.ReadBytes(GetIntegerSize(binr));
                rsaParameters.D = binr.ReadBytes(GetIntegerSize(binr));
                rsaParameters.P = binr.ReadBytes(GetIntegerSize(binr));
                rsaParameters.Q = binr.ReadBytes(GetIntegerSize(binr));
                rsaParameters.DP = binr.ReadBytes(GetIntegerSize(binr));
                rsaParameters.DQ = binr.ReadBytes(GetIntegerSize(binr));
                rsaParameters.InverseQ = binr.ReadBytes(GetIntegerSize(binr));
            }

            rsa.ImportParameters(rsaParameters);
            return rsa;
        }

        private static int GetIntegerSize(BinaryReader binr)
        {
            byte bt = 0;
            int count = 0;
            bt = binr.ReadByte();
            if (bt != 0x02)
                return 0;
            bt = binr.ReadByte();

            if (bt == 0x81)
                count = binr.ReadByte();
            else
            if (bt == 0x82)
            {
                var highbyte = binr.ReadByte();
                var lowbyte = binr.ReadByte();
                byte[] modint = { lowbyte, highbyte, 0x00, 0x00 };
                count = BitConverter.ToInt32(modint, 0);
            }
            else
            {
                count = bt;
            }

            while (binr.ReadByte() == 0x00)
            {
                count -= 1;
            }
            binr.BaseStream.Seek(-1, SeekOrigin.Current);
            return count;
        }



        /// <summary>
        /// 使用公钥验证签名
        /// </summary>
        /// <param name="data">原始数据</param>
        /// <param name="sign">签名</param>
        /// <returns></returns>
        public bool VerifySign(string xmlPublicKey, byte[] SourceBytes, byte[] signBytes)
        {
            // byte[] dataBytes = _encoding.GetBytes(data);
            // byte[] signBytes = Convert.FromBase64String(sign);

            using (RSACryptoServiceProvider _privateKeyRsaProvider = new RSACryptoServiceProvider())
            {
                _privateKeyRsaProvider.FromXmlString(xmlPublicKey);
                var verify = _privateKeyRsaProvider.VerifyData(SourceBytes, signBytes, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1);

                return verify;
            }
        }



        public static X509Certificate2 getPrivateKeyXmlFromPFX(string PFX_file, string password)
        {
            return new X509Certificate2(PFX_file, password, X509KeyStorageFlags.Exportable);
        }

        public static X509Certificate2 getPublicKeyXmlFromCer(string Cer_file)
        {
            return new X509Certificate2(Cer_file);
        }


        public static byte[] CreateSignWithPrivateKey(byte[] msgin, X509Certificate2 pfx)
        {
            HashAlgorithm SHA1 = HashAlgorithm.Create("sha1");
            byte[] hashdata = SHA1.ComputeHash(msgin);//求数字指纹

            try
            {
                AsymmetricAlgorithm prikey = pfx.PrivateKey;
            }
            catch (Exception er)
            {
                Console.WriteLine(er.ToString());
            }

            RSAPKCS1SignatureFormatter signCrt = new RSAPKCS1SignatureFormatter();
            signCrt.SetKey(pfx.PrivateKey);
            signCrt.SetHashAlgorithm("sha1");
            return signCrt.CreateSignature(hashdata);
        }

        public static bool VerifySignWithPublicKey(byte[] msgin, X509Certificate2 cer, byte[] sign)
        {
            HashAlgorithm SHA1 = HashAlgorithm.Create("sha1");
            byte[] hashdata = SHA1.ComputeHash(msgin);//求数字指纹

            RSACryptoServiceProvider signV = new RSACryptoServiceProvider();
            signV.FromXmlString(cer.PublicKey.Key.ToXmlString(false));
            return signV.VerifyData(msgin, CryptoConfig.MapNameToOID("SHA1"), sign);
        }

        public static string Base64Encoder(byte[] b)
        {
            return Convert.ToBase64String(b);
        }

        public static byte[] Base64Decoder(string base64String)
        {
            return Convert.FromBase64String(base64String);
        }




        public class MessageWorker
        {
            //string loggerHeader = "MessageWorker_";
            public struct trafficMessage
            {
                public string charset;  //合作商户ID 杉德系统分配，唯一标识
                public string signType;// 加密后的AES秘钥 公钥加密(RSA/ECB/PKCS1Padding)，加密结果采用base64编码
                public string data; //加密后的请求/应答报文 AES加密(AES/ECB/PKCS5Padding)，加密结果采用base64编码
                public string sign;//    签名 对encryptData对应的明文进行签名(SHA1WithRSA)，签名结果采用base64编码
                public string extend;//  扩展域 暂时不用
            }
            private Encoding encodeCode = Encoding.UTF8;


            private string pfxFilePath = string.Empty;
            public string PFXFile
            {
                get
                {
                    return pfxFilePath;
                }
                set
                {
                    pfxFilePath = value;
                }
            }

            private string pfxPassword = string.Empty;
            public string PFXPassword
            {
                get
                {
                    return pfxPassword;
                }
                set
                {
                    pfxPassword = value;
                }
            }


            private string cerFilePath = string.Empty;
            public string CerFile
            {
                get
                {
                    return cerFilePath;
                }
                set
                {
                    cerFilePath = value;
                }
            }
            public trafficMessage UrlDecodeMessage(string msgResponse)
            {
                trafficMessage msgEncrypt = new trafficMessage();
                string rawRespMessage = System.Web.HttpUtility.UrlDecode(msgResponse);
                Dictionary<string, string> EncryptBody = CryptUtils.ParseKeyValueString(rawRespMessage);
                msgEncrypt.charset = EncryptBody.ContainsKey("charset") ? EncryptBody["charset"] : "";
                msgEncrypt.signType = EncryptBody.ContainsKey("signType") ? EncryptBody["signType"] : "";
                msgEncrypt.data = EncryptBody.ContainsKey("data") ? EncryptBody["data"] : "";
                msgEncrypt.sign = EncryptBody.ContainsKey("sign") ? EncryptBody["sign"] : "";
                msgEncrypt.extend = EncryptBody.ContainsKey("extend") ? EncryptBody["extend"] : "";
                return msgEncrypt;
            }

            public string UrlEncodeMessage(trafficMessage msgRequest)
            {
                //需要添加引用System.Web，用于url转码，处理base64产生的+/=
                return "charset=" + System.Web.HttpUtility.UrlEncode(msgRequest.charset) + "&" +
                     "signType=" + System.Web.HttpUtility.UrlEncode(msgRequest.signType) + "&" +
                      "data=" + System.Web.HttpUtility.UrlEncode(msgRequest.data) + "&" +
                       "sign=" + System.Web.HttpUtility.UrlEncode(msgRequest.sign) + "&" +
                       "extend=" + System.Web.HttpUtility.UrlEncode(msgRequest.extend);
            }



            public trafficMessage SignMessageBeforePost(trafficMessage msgSource)
            {
                trafficMessage msgEncrypt = new trafficMessage();


                //获取报文字符集
                this.encodeCode = Encoding.GetEncoding(msgSource.charset);
                //Logger.Logging(loggerHeader, "Message Charset is [" + msgSource.charset + "]", true);

                msgEncrypt.charset = msgSource.charset;
                msgEncrypt.signType = msgSource.signType;
                msgEncrypt.extend = msgSource.extend;
                msgEncrypt.data = msgSource.data;

                //报文签名
                msgEncrypt.sign = CryptUtils.Base64Encoder(CryptUtils.CreateSignWithPrivateKey(CryptUtils.getBytesFromString(msgSource.data, encodeCode),
                    CryptUtils.getPrivateKeyXmlFromPFX(pfxFilePath, pfxPassword)));

                //Logger.Logging(loggerHeader, "sign[" + msgEncrypt.sign + "]", true);

                return msgEncrypt;

            }
            public trafficMessage CheckSignMessageAfterResponse(trafficMessage msgEncrypt)
            {
                trafficMessage msgSource = new trafficMessage();

                //获取报文字符集
                this.encodeCode = Encoding.GetEncoding(msgEncrypt.charset);
                //Logger.Logging(loggerHeader, "Message Charset is [" + msgEncrypt.charset + "]", true);

                msgSource.charset = msgEncrypt.charset;
                msgSource.signType = msgEncrypt.signType;
                msgSource.extend = msgEncrypt.extend;
                msgSource.data = msgEncrypt.data;

                msgSource.sign = CryptUtils.VerifySignWithPublicKey(
                                    (CryptUtils.getBytesFromString(msgEncrypt.data, encodeCode)),
                                    CryptUtils.getPublicKeyXmlFromCer(cerFilePath),
                                    CryptUtils.Base64Decoder(msgEncrypt.sign)
                                    ).ToString();

                //Logger.Logging(loggerHeader, "sign[" + msgSource.sign + "][" + msgEncrypt.sign + "]", true);
                return msgSource;
            }


            public trafficMessage postMessage(string serverUrl, trafficMessage requestSourceMessage)
            {
                trafficMessage responseMessage = new trafficMessage();
                try
                {
                    string requestString = UrlEncodeMessage(SignMessageBeforePost(requestSourceMessage));
                    //Console.WriteLine("url:" + serverUrl);
                    //Logger.Logging(loggerHeader, "request  ==>[" + requestString + "]", true);

                    string responseString = HttpUtils.HttpPost(serverUrl, requestString, encodeCode);
                    //Logger.Logging(loggerHeader, "response <==[" + responseString + "]", true);
                    responseMessage = CheckSignMessageAfterResponse(UrlDecodeMessage(responseString));
                }
                catch (Exception er)
                {
                    Console.WriteLine(er.ToString());
                }
                return responseMessage;
            }
        }

        public class MessageCryptWorker
        {

            public struct trafficMessage
            {
                public string transCode;//交易码 根据具体业务定义
                public string merId;  //合作商户ID 杉德系统分配，唯一标识
                public string encryptKey;// 加密后的AES秘钥 公钥加密(RSA/ECB/PKCS1Padding)，加密结果采用base64编码
                public string encryptData; //加密后的请求/应答报文 AES加密(AES/ECB/PKCS5Padding)，加密结果采用base64编码
                public string sign;//    签名 对encryptData对应的明文进行签名(SHA1WithRSA)，签名结果采用base64编码
                public string extend;//  扩展域 暂时不用
                public string plId;// 平台商户号
                public string accessType;// 接入方式 0=普通商户 1 平台商户

            }


            private Encoding encodeCode = Encoding.UTF8;
            public Encoding EncodeCode
            {
                get
                {
                    return encodeCode;
                }
                set
                {
                    encodeCode = value;
                }
            }


            private string pfxFilePath = string.Empty;
            public string PFXFile
            {
                get
                {
                    return pfxFilePath;
                }
                set
                {
                    pfxFilePath = value;
                }
            }

            private string pfxPassword = string.Empty;
            public string PFXPassword
            {
                get
                {
                    return pfxPassword;
                }
                set
                {
                    pfxPassword = value;
                }
            }


            private string cerFilePath = string.Empty;
            public string CerFile
            {
                get
                {
                    return cerFilePath;
                }
                set
                {
                    cerFilePath = value;
                }
            }

            private trafficMessage EncryptMessageBeforePost(trafficMessage msgSource)
            {

                //public string transCode;//交易码 根据具体业务定义
                //public string merId;  //合作商户ID 杉德系统分配，唯一标识
                //public string encryptKey;// 加密后的AES秘钥 公钥加密(RSA/ECB/PKCS1Padding)，加密结果采用base64编码
                //public string encryptData; //加密后的请求/应答报文 AES加密(AES/ECB/PKCS5Padding)，加密结果采用base64编码
                //public string sign;//    签名 对encryptData对应的明文进行签名(SHA1WithRSA)，签名结果采用base64编码
                //public string extend;//  扩展域 暂时不用
                //public string plId;// 平台商户号
                //public string accessType;// 接入方式 0=普通商户 1 平台商户

                trafficMessage msgEncrypt = new trafficMessage();
                //随机生成16位密钥
                msgSource.encryptKey = CryptUtils.GuidTo16String();
                //log.Debug("Generated local AESkey [" + msgSource.encryptKey + "]");

                //encryptKey加密，杉德公钥RSA加密
                msgEncrypt.encryptKey = CryptUtils.Base64Encoder(CryptUtils.RSAEncrypt(CryptUtils.getPublicKeyXmlFromCer(cerFilePath).PublicKey.Key.ToXmlString(false),
                    CryptUtils.getBytesFromString(msgSource.encryptKey, encodeCode)));

                //log.Debug("encryptKey[" + msgSource.encryptKey + "][" + msgEncrypt.encryptKey + "]");


                msgEncrypt.transCode = msgSource.transCode;
                msgEncrypt.merId = msgSource.merId;
                msgEncrypt.extend = msgSource.extend;
                msgEncrypt.plId = msgSource.plId;
                msgEncrypt.accessType = msgSource.accessType;

                //encryptData加密，AES加密
                msgEncrypt.encryptData = CryptUtils.Base64Encoder(CryptUtils.AESEncrypt(CryptUtils.getBytesFromString(msgSource.encryptData, encodeCode),
                    msgSource.encryptKey));

                //log.Debug("encryptData[" + msgSource.encryptData + "][" + msgEncrypt.encryptData + "]");

                msgEncrypt.sign = CryptUtils.Base64Encoder(CryptUtils.CreateSignWithPrivateKey(CryptUtils.getBytesFromString(msgSource.encryptData, encodeCode),
                    CryptUtils.getPrivateKeyXmlFromPFX(pfxFilePath, pfxPassword)));

                //log.Debug("sign[" + msgEncrypt.sign + "]");

                return msgEncrypt;

            }
            public trafficMessage DecryptMessageAfterResponse(trafficMessage msgEncrypt)
            {
                trafficMessage msgSource = new trafficMessage();
                msgSource.transCode = msgEncrypt.transCode;
                msgSource.merId = msgEncrypt.merId;
                msgSource.extend = msgEncrypt.extend;

                msgSource.plId = msgEncrypt.plId;
                msgSource.accessType = msgEncrypt.accessType;

                msgSource.encryptKey = CryptUtils.getStringFromBytes(CryptUtils.RSADecrypt(CryptUtils.getPrivateKeyXmlFromPFX(pfxFilePath, pfxPassword).PrivateKey.ToXmlString(true),
                    CryptUtils.Base64Decoder(msgEncrypt.encryptKey)), encodeCode);
                //log.Debug("encryptKey[" + msgSource.encryptKey + "]);

                byte[] sourceByte = CryptUtils.AESDecrypt(CryptUtils.Base64Decoder(msgEncrypt.encryptData),
                    msgSource.encryptKey);
                msgSource.encryptData = CryptUtils.getStringFromBytes(sourceByte, encodeCode);
                // log.Debug("encryptData[" + msgSource.encryptData + "][" + msgEncrypt.encryptData + "]");

                msgSource.sign =
                    CryptUtils.VerifySignWithPublicKey(
                        sourceByte,
                        CryptUtils.getPublicKeyXmlFromCer(cerFilePath),
                        CryptUtils.Base64Decoder(msgEncrypt.sign)
                        ).ToString();

                // log.Debug("sign[" + msgSource.sign + "][" + msgEncrypt.sign + "]");
                //需要添加引用 System.Web
                return msgSource;
            }

            private trafficMessage UrlDecodeMessage(string msgResponse)
            {
                trafficMessage msgEncrypt = new trafficMessage();
                string[] EncryptBody = msgResponse.Split('&');
                for (int i = 0; i < EncryptBody.Length; i++)
                {
                    string[] tmp = EncryptBody[i].Split('=');
                    switch (tmp[0])
                    {
                        //需要添加引用System.Web，用于url转码，处理base64产生的+/=
                        case "plId": msgEncrypt.plId = System.Web.HttpUtility.UrlDecode(EncryptBody[i].Replace("plId=", "").Trim('"')); break;
                        case "accessType": msgEncrypt.accessType = System.Web.HttpUtility.UrlDecode(EncryptBody[i].Replace("accessType=", "").Trim('"')); break;
                        case "transCode": msgEncrypt.transCode = System.Web.HttpUtility.UrlDecode(EncryptBody[i].Replace("transCode=", "").Trim('"')); break;
                        case "merId": msgEncrypt.merId = System.Web.HttpUtility.UrlDecode(EncryptBody[i].Replace("merId=", "").Trim('"')); break;
                        case "encryptKey": msgEncrypt.encryptKey = System.Web.HttpUtility.UrlDecode(EncryptBody[i].Replace("encryptKey=", "").Trim('"')); break;
                        case "encryptData": msgEncrypt.encryptData = System.Web.HttpUtility.UrlDecode(EncryptBody[i].Replace("encryptData=", "").Trim('"')); break;
                        case "sign": msgEncrypt.sign = System.Web.HttpUtility.UrlDecode(EncryptBody[i].Replace("sign=", "").Trim('"')); break;
                        case "extend": msgEncrypt.extend = System.Web.HttpUtility.UrlDecode(EncryptBody[i].Replace("extend=", "").Trim('"')); break;
                    }
                }
                return msgEncrypt;
            }
            private string UrlEncodeMessage(trafficMessage msgRequest)
            {
                //需要添加引用System.Web，用于url转码，处理base64产生的+/=
                return "transCode=" + System.Web.HttpUtility.UrlEncode(msgRequest.transCode) + "&" +
                     "plId=" + System.Web.HttpUtility.UrlEncode(msgRequest.plId) + "&" +
                     "accessType=" + System.Web.HttpUtility.UrlEncode(msgRequest.accessType) + "&" +
                     "merId=" + System.Web.HttpUtility.UrlEncode(msgRequest.merId) + "&" +
                      "encryptKey=" + System.Web.HttpUtility.UrlEncode(msgRequest.encryptKey) + "&" +
                       "encryptData=" + System.Web.HttpUtility.UrlEncode(msgRequest.encryptData) + "&" +
                       "sign=" + System.Web.HttpUtility.UrlEncode(msgRequest.sign) + "&" +
                       "extend=" + System.Web.HttpUtility.UrlEncode(msgRequest.extend);
            }

            public trafficMessage postMessage(string serverUrl, trafficMessage requestSourceMessage, CookieContainer cookies = null)
            {
                trafficMessage responseMessage = new trafficMessage();
                try
                {
                    string requestString = UrlEncodeMessage(EncryptMessageBeforePost(requestSourceMessage));

                    string responseString = HttpUtils.HttpPost(serverUrl, requestString, encodeCode);

                    responseMessage = DecryptMessageAfterResponse(UrlDecodeMessage(responseString));
                }
                catch (Exception er)
                {
                    responseMessage.extend = er.ToString();
                }
                return responseMessage;
            }
        }
        public class HttpUtils
        {
            public static string HttpPost(string postUrl, string paramData, Encoding EncodingName)
            {
                string postDataStr = paramData;
                byte[] buff = EncodingName.GetBytes(postDataStr);

                HttpWebRequest request = null;
                //如果是发送HTTPS请求  
                if (postUrl.StartsWith("https", StringComparison.OrdinalIgnoreCase))
                {
                    ServicePointManager.ServerCertificateValidationCallback = new RemoteCertificateValidationCallback(CheckValidationResult);
                    request = WebRequest.Create(postUrl) as HttpWebRequest;
                    request.ProtocolVersion = HttpVersion.Version10;
                }
                else
                {
                    request = WebRequest.Create(postUrl) as HttpWebRequest;
                }

                request.Method = "POST";
                request.ContentType = "application/x-www-form-urlencoded";

                Stream myRequestStream = request.GetRequestStream();
                myRequestStream.Write(buff, 0, buff.Length);
                myRequestStream.Close();

                HttpWebResponse response = (HttpWebResponse)request.GetResponse();
                Stream myResponseStream = response.GetResponseStream();
                StreamReader myStreamReader = new StreamReader(myResponseStream, EncodingName);
                string retString = myStreamReader.ReadToEnd();
                myStreamReader.Close();
                myResponseStream.Close();
                return retString;
            }

            private static bool CheckValidationResult(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors errors)
            {
                return true; //总是接受 ，注意生产环境要根据实际证书验证情况而判断
            }
        }
    }

}
